package bma.common.httpclient;

import java.util.concurrent.TimeUnit;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.HttpParams;

public class HttpClientPool implements HttpClientFactory {

	public class IdleConnectionMonitorThread extends Thread {

		private volatile boolean shutdown;

		public IdleConnectionMonitorThread() {
			super();
		}

		@Override
		public void run() {
			try {
				while (!shutdown) {
					synchronized (this) {
						wait(idleCheckTime);
						ThreadSafeClientConnManager m = clientManager;
						if (m == null)
							return;
						// Close expired connections
						m.closeExpiredConnections();
						// Optionally, close connections
						// that have been idle connection
						m.closeIdleConnections(idleTime, TimeUnit.SECONDS);
					}
				}
			} catch (InterruptedException ex) {
				// terminate
			}
		}

		public void shutdown() {
			shutdown = true;
			synchronized (this) {
				notifyAll();
			}
		}

	}

	private int maxTotal;
	private int defaultMaxPerRoute;
	private int idleTime = 30;
	private long idleCheckTime = 5000;

	private transient ThreadSafeClientConnManager clientManager;
	private transient IdleConnectionMonitorThread idleChecker;

	public ThreadSafeClientConnManager getClientManager() {
		return clientManager;
	}

	public int getMaxTotal() {
		return maxTotal;
	}

	public void setMaxTotal(int maxPool) {
		this.maxTotal = maxPool;
	}

	public int getDefaultMaxPerRoute() {
		return defaultMaxPerRoute;
	}

	public void setDefaultMaxPerRoute(int defaultMaxPerRoute) {
		this.defaultMaxPerRoute = defaultMaxPerRoute;
	}

	public int getIdleTime() {
		return idleTime;
	}

	public void setIdleTime(int idleTime) {
		this.idleTime = idleTime;
	}

	public long getIdleCheckTime() {
		return idleCheckTime;
	}

	public void setIdleCheckTime(long idleCheckTime) {
		this.idleCheckTime = idleCheckTime;
	}

	public void start() {
		if (this.clientManager == null) {
			this.clientManager = new ThreadSafeClientConnManager();
			if (this.maxTotal > 0) {
				this.clientManager.setMaxTotal(this.maxTotal);
			}
			if (this.defaultMaxPerRoute > 0) {
				this.clientManager
						.setDefaultMaxPerRoute(this.defaultMaxPerRoute);
			}
		}
		if (this.idleChecker == null) {
			this.idleChecker = new IdleConnectionMonitorThread();
			this.idleChecker.start();
		}
	}

	public void stop() {
		if (this.idleChecker != null) {
			this.idleChecker.shutdown();
			this.idleChecker = null;
		}
		if (this.clientManager != null) {
			this.clientManager.shutdown();
			this.clientManager = null;
		}
	}

	@Override
	public DefaultHttpClient createClient(HttpParams params) {
		if (params == null) {
			return new DefaultHttpClient(this.clientManager);
		}
		return new DefaultHttpClient(this.clientManager, params);
	}
}
